package actionListener;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import javax.swing.JButton;

import miniMax.TicTacToeFramework;
import simpleTicTacToe.SimpleGame;

import computerPlayer.HumanPlayer;
import computerPlayer.Player;

import controller.Controlleriface;

public class ButtonListener implements ActionListener {

	private Controlleriface controller;
	private TicTacToeFramework model;
	// The members
	private Player one;
	private Player two;
	private int counter;
	private Random r = new Random();
	private final String[] chars = { "O", "X", "Y" };
	private final List<String> charList = new LinkedList<String>(
			Arrays.asList(chars));

	public ButtonListener(Controlleriface controller) {
		this.controller = controller;
	}

	public void actionPerformed(ActionEvent e) {
		JButton source = (JButton) e.getSource();
		if (source.equals(getView().getStart())) {
			readAndInitPlayer();
			chooseBeginner();
			System.out.println("Spieler 1: "
					+ controller.getOne().getPlayerName() + "("
					+ controller.getOne().getPlayerChar() + ")" + "["
					+ controller.getOne().getClass().getSimpleName() + "]");
			System.out.println("Spieler 2: "
					+ controller.getTwo().getPlayerName() + "("
					+ controller.getTwo().getPlayerChar() + ")" + "["
					+ controller.getTwo().getClass().getSimpleName() + "]");
			controller.setNameLabel("Spieler "
					+ controller.getActualPlayer().getPlayerName()
					+ " ist dran.");
			controller.resetGame();
			controller.resetWins();
			getView().getStart().setEnabled(false);
			getView().getRestart().setEnabled(false);
			controller.activate();
			
			controller.gameLoop();
			

		} else if (source.equals(getView().getRestart())) {
			if (controller.getOne() == null) {
				readAndInitPlayer();
			}
			chooseBeginner();
			controller.resetGame();
			getView().getStart().setEnabled(false);
			getView().getRestart().setEnabled(false);
			controller.activate();
			controller.setNameLabel("Spieler "
					+ controller.getActualPlayer().getPlayerName()
					+ " ist dran.");
			controller.gameLoop();
		}
	}

	private void readAndInitPlayer() {
		/*
		 * The start button is pressed. Now get the information from the west
		 * and east label.
		 */

		/* Generate a new model. This is the only model to be used. */
		model = TicTacToeFramework.getTicTacToeFrameWork();

		/* Set the both player */

		/* "west" is player one */
		String playerName = getView().getCppWest().getNameLabel().getText();
		String playerChar = getView().getCppWest().getCharLabel().getText();
		if (playerChar.length() > 1) {
			playerChar = playerChar.substring(0, 1);
		}
		controller.setOne(initPlayer(getView().getCppWest().getChoosenPlayer(),
				playerName, playerChar));

		/* east is player two */
		playerName = getView().getCppEast().getNameLabel().getText();
		playerChar = getView().getCppEast().getCharLabel().getText();
		if (playerChar.length() > 1) {
			playerChar = playerChar.substring(0, 1);
		}
		controller.setTwo(initPlayer(getView().getCppEast().getChoosenPlayer(),
				playerName, playerChar));

		/* Check chars */
		String charOne = controller.getOne().getPlayerChar();
		String charTwo = controller.getTwo().getPlayerChar();
		if (charOne.equals(charTwo)) {
			if (charList.contains(charOne) && charList.contains(charTwo)) {
				for (String charParam : charList) {
					if (!charParam.equals(charOne)
							&& !charParam.equals(charTwo)) {
						charOne = charParam;
						break;
					}
				}
			} else {
				charOne = charList.get(0);
				controller.getOne().setPlayerChar(charOne);
			}
		}

		/* make them know each other */
		controller.getOne().setOtherPlayer(controller.getTwo());
		controller.getTwo().setOtherPlayer(controller.getOne());
		
		controller.getView().getCppWest().getNameLabel().setText(controller.getOne().getPlayerName());
		controller.getView().getCppWest().getCharLabel().setText(controller.getOne().getPlayerChar());
		
		controller.getView().getCppEast().getNameLabel().setText(controller.getTwo().getPlayerName());
		controller.getView().getCppEast().getCharLabel().setText(controller.getTwo().getPlayerChar());

		controller.actualize();
	}

	private void chooseBeginner() {
		/* Set the Beginner */
		if (controller.getView().getOneCheckbox()) {
			counter = 0;
		} else if (controller.getView().getTwoCheckbox()) {
			counter = 1;
		} else {
			/* randomly choose the beginner */
			counter = r.nextInt();
		}
		if (counter % 2 == 0) {
			controller.setActualPlayer(controller.getOne());
		} else {
			controller.setActualPlayer(controller.getTwo());
		}
	}

	public Player initPlayer(String playerKlasse, String playerName,
			String playerChar) {

		Player player = null;

		if (playerKlasse.equals("HumanPlayer")) {
			/*
			 * public HumanPlayer(PlayTicTacToe controller, String
			 * playerCharPar, String playerNamePar, TicTacToe view) {
			 */
			
			return new HumanPlayer(playerChar, playerName);
//			try {
//				Class<HumanPlayer> oneTmp = HumanPlayer.class;
//				@SuppressWarnings("rawtypes")
//				Class[] params = new Class[2];
//				params[0] = String.class;
//				params[1] = String.class;
//
//				Constructor<HumanPlayer> oConstr = oneTmp
//						.getConstructor(params);
//				Object[] aoParams = new Object[2];
//				aoParams[0] = playerChar;
//				;
//				aoParams[1] = playerName;
//
//				player = oConstr.newInstance(aoParams);
//			} catch (IllegalArgumentException e) {
//				e.printStackTrace();
//			} catch (InstantiationException e) {
//				e.printStackTrace();
//			} catch (IllegalAccessException e) {
//				e.printStackTrace();
//			} catch (InvocationTargetException e) {
//				e.printStackTrace();
//			} catch (SecurityException e) {
//				e.printStackTrace();
//			} catch (NoSuchMethodException e) {
//				e.printStackTrace();
//			}
		} else {
			try {
				Class<?> oneTmp = Class.forName("computerPlayer."
						+ playerKlasse);
				@SuppressWarnings("rawtypes")
				Class[] params = new Class[2];
				params[0] = TicTacToeFramework.class;
				params[1] = Player.class;

				Constructor<?> oConstr = oneTmp.getConstructor(params);
				Object[] aoParams = new Object[2];
				aoParams[0] = model;
				;
				aoParams[1] = null;

				player = (Player) oConstr.newInstance(aoParams);
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
		return player;

	}

	public Player getOne() {
		return one;
	}

	public void setOne(Player one) {
		this.one = one;
	}

	public Player getTwo() {
		return two;
	}

	public void setTwo(Player two) {
		this.two = two;
	}

	public SimpleGame getView() {
		return controller.getView();
	}

}
